package cn.hit;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;

import cn.hit.constant.HitConstants;
import cn.hit.jdbc.DBAccessSington;
import cn.hit.thread.CreateSqlWithExcelThread;
import cn.hit.thread.ExecuteExportFileThread;
import cn.hit.thread.ExecuteSqlThread;
import cn.hit.thread.ExportFileBySVNNumberThread;
import cn.hit.thread.GenerateTestDataThread;

@SuppressWarnings("serial")
public class ExecuteSqlWin extends JFrame {
    private BufferedReader reader;
    private JFileChooser chooser;

    private DBAccessSington dbAccess;
    private JTextField url;
    private JTextField userName;
    private JPasswordField pwd;

    private String currentDir;
    private JTextField importPath;
    private JButton importButt;
    private JTextField exportPath;
    private JButton exportButt;

    private JButton generateTestDataButt;
    private JButton exportFileBySVNNumberButt;
    private JButton exportFileButt;
    private JButton executeButt;

    private JTextArea logArea;

    private JProgressBar pbar;
    private JPanel bottomArea;

    private ExecuteExportFileThread executeExportFileThread;
    private ExecuteSqlThread executeSqlThread;
    private CreateSqlWithExcelThread createSqlWithExcelThread;
    private ExportFileBySVNNumberThread efbsn;
    private GenerateTestDataThread generateTestDataThread;

    public ExecuteSqlWin() {
        // 主窗口的设置
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle(HitConstants.MAIN_WIN_TITLE);
        setLocation(300, 200);
        setSize(800, 510);
        setResizable(true);
        setLayout(new BorderLayout());

        // 初始化数据库连接
        dbAccess = DBAccessSington.getInstance();

        // 找到本程序运行时的绝对路径
        try {
            currentDir = new File(".").getCanonicalPath();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        /* ============================================================== */
        /* 窗口分为4个部分：连接区、选择文件区、Log区、底部区 */
        /* ============================================================== */

        /* ===============连接区：包括urlPanel、accountPanel=============== */
        JPanel connAera = new JPanel();
        connAera.setLayout(new BorderLayout());

        JPanel urlPanel = new JPanel();
        urlPanel.setLayout(new BorderLayout());
        Label urlLabel = new Label(HitConstants.DB_URL_LABEL);
        url = new JTextField(HitConstants.DB_DEFAULT_URL);
        urlPanel.add(urlLabel, BorderLayout.WEST);
        urlPanel.add(url, BorderLayout.CENTER);

        JPanel accountPanel = new JPanel();
        accountPanel.setLayout(new GridLayout(1, 2));

        JPanel namePanel = new JPanel();
        namePanel.setLayout(new BorderLayout());
        Label nameLabel = new Label(HitConstants.DB_USER_NAME_LABEL);
        userName = new JTextField(HitConstants.DB_DEFAULT_USER_NAME);
        namePanel.add(nameLabel, BorderLayout.WEST);
        namePanel.add(userName, BorderLayout.CENTER);
        JPanel pwdPanel = new JPanel();
        pwdPanel.setLayout(new BorderLayout());
        Label pwdLabel = new Label(HitConstants.DB_USER_PASSWORD_LABEL);
        pwd = new JPasswordField(HitConstants.DB_DEFAULT_USER_PASSWORD);
        pwdPanel.add(pwdLabel, BorderLayout.WEST);
        pwdPanel.add(pwd, BorderLayout.CENTER);

        accountPanel.add(namePanel);
        accountPanel.add(pwdPanel);

        connAera.add(urlPanel, BorderLayout.NORTH);
        connAera.add(accountPanel, BorderLayout.CENTER);

        /* ===============选择文件区：包括importPanel、exportPanel=============== */
        JPanel fileAera = new JPanel();
        fileAera.setLayout(new BorderLayout());

        JPanel importPanel = new JPanel();
        importPath = new JTextField();
        importButt = new JButton(HitConstants.BUTTON_CHOOSE_FILE_LABEL);
        importButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fileChoose();
            }
        });
        exportPath = new JTextField(currentDir);
        exportButt = new JButton(HitConstants.BUTTON_CHOOSE_FILE_LABEL);
        exportButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dirChoose(exportPath);
            }
        });
        Label importLabel = new Label(HitConstants.INPUT_CHOOSE_SOURCE_LIST_LABEL);
        importPanel.setLayout(new BorderLayout());
        importPanel.add(importLabel, BorderLayout.WEST);
        importPanel.add(importPath, BorderLayout.CENTER);
        importPanel.add(importButt, BorderLayout.EAST);
        importPanel.add(connAera, BorderLayout.NORTH);

        JPanel exportPanel = new JPanel();
        Label exportLabel = new Label(HitConstants.INPUT_EXECUTE_SOURCE_PATH_LABEL);
        exportPanel.setLayout(new BorderLayout());
        exportPanel.add(exportLabel, BorderLayout.WEST);
        exportPanel.add(exportPath, BorderLayout.CENTER);
        exportPanel.add(exportButt, BorderLayout.EAST);

        fileAera.add(importPanel, BorderLayout.NORTH);
        fileAera.add(exportPanel, BorderLayout.CENTER);
        add(fileAera, BorderLayout.NORTH);

        /* ===============Log区============== */
        logArea = new JTextArea();
        JScrollPane scrollPanel = new JScrollPane(logArea);
        scrollPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        logArea.setEditable(false);
        add(scrollPanel, BorderLayout.CENTER);

        /* =============== 底部区：包括btmButtPanel、pbar=============== */
        bottomArea = new JPanel();
        bottomArea.setLayout(new BorderLayout());
        JPanel btmButtPanel = new JPanel();
        btmButtPanel.setLayout(new GridLayout(1, 7));

        /* =============== 导出测试数据=============== */
        generateTestDataButt = new JButton(HitConstants.BUTTON_GENERATE_TESTDATA_LABEL);
        btmButtPanel.add(generateTestDataButt);

        /* =============== 为按钮区的布局，添加辅助空Label=============== */
        btmButtPanel.add(new Label());
        btmButtPanel.add(new Label());
        btmButtPanel.add(new Label());

        /* =============== 根据SVN输出文件=============== */
        exportFileBySVNNumberButt = new JButton(HitConstants.BUTTON_CALL_SVN_WIN_LABEL);
        btmButtPanel.add(exportFileBySVNNumberButt);

        /* =============== 执行导出脚本 =============== */
        exportFileButt = new JButton(HitConstants.BUTTON_EXPORT_FILE_LABEL);
        btmButtPanel.add(exportFileButt);

        /* =============== 执行脚本=============== */
        executeButt = new JButton(HitConstants.BUTTON_EXECUTE_FILE_LABEL);
        btmButtPanel.add(executeButt);

        pbar = new JProgressBar();
        pbar.setVisible(false);
        bottomArea.add(pbar, BorderLayout.NORTH);
        bottomArea.add(btmButtPanel, BorderLayout.CENTER);
        add(bottomArea, BorderLayout.SOUTH);
    }

    /**
     * 主窗口按钮添加监听
     */
    public void addListeners() {
        // 生成测试数据按钮添加监听
        addListenerToGenerateTestDataButton();
        // 为根据svn导出文件按钮添加监听
        addListenerToExportFileBySVNNumberButton();
        // 为执行导出脚本按钮添加监听
        addListenerToExportFileButton();
        // 为执行脚本按钮添加监听
        addListenerToExecuteButton();
    }

    /**
     * 为生成测试数据按钮添加监听
     */
    private void addListenerToGenerateTestDataButton() {
        generateTestDataButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (importPath.getText().trim().equals("")) {
                    logArea.setText("********没有资源列表********");
                } else {
                    generateTestDataThread = new GenerateTestDataThread(ExecuteSqlWin.this);
                    generateTestDataThread.start();
                }
            }
        });
    }

    /**
     * 为根据svn导出文件按钮添加监听
     */
    private void addListenerToExportFileBySVNNumberButton() {
        exportFileBySVNNumberButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                final JDialog dialog = new JDialog(ExecuteSqlWin.this,
                        HitConstants.BUTTON_CALL_SVN_WIN_LABEL, true);
                dialog.setBounds(500, 400, 400, 120);

                Label dRootLabel = new Label(HitConstants.SVN_SCOURCE_PATH_LABEL);
                final JTextField dRootPath = new JTextField();
                JButton dRootButt = new JButton(HitConstants.BUTTON_CHOOSE_FILE_LABEL);
                JPanel rootPanel = new JPanel();
                rootPanel.setLayout(new BorderLayout());
                rootPanel.add(dRootLabel, BorderLayout.WEST);
                rootPanel.add(dRootPath, BorderLayout.CENTER);
                rootPanel.add(dRootButt, BorderLayout.EAST);
                dRootButt.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        dirChoose(dRootPath);
                    }
                });

                Label dExportLabel = new Label(HitConstants.SVN_EXPORT_PATH_LABEL);
                final JTextField dExportPath = new JTextField();
                JButton dExportButt = new JButton(HitConstants.BUTTON_CHOOSE_FILE_LABEL);
                JPanel exportPanel = new JPanel();
                exportPanel.setLayout(new BorderLayout());
                exportPanel.add(dExportLabel, BorderLayout.WEST);
                exportPanel.add(dExportPath, BorderLayout.CENTER);
                exportPanel.add(dExportButt, BorderLayout.EAST);
                dExportButt.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        dirChoose(dExportPath);
                    }
                });

                Label dLabel = new Label(HitConstants.SVN_VERSION_NO_LABEL);
                final JTextField dSVNNumber = new JTextField();
                JButton dButt = new JButton(HitConstants.BUTTON_YES_LABEL);
                JPanel SVNNumberPanel = new JPanel();
                SVNNumberPanel.setLayout(new BorderLayout());
                SVNNumberPanel.add(dLabel, BorderLayout.WEST);
                SVNNumberPanel.add(dSVNNumber, BorderLayout.CENTER);
                SVNNumberPanel.add(dButt, BorderLayout.EAST);

                dButt.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        dialog.dispose();
                        String rootPath = dRootPath.getText().trim();
                        if (rootPath.equals("")) {
                            logArea.setText("******资源路径不能为空******");
                            return;
                        }
                        String exportPath = dExportPath.getText().trim();
                        if (exportPath.equals("")) {
                            logArea.setText("******输出路径不能为空******");
                            return;
                        }
                        String SVNStr = dSVNNumber.getText().trim();
                        if (SVNStr.equals("")) {
                            logArea.setText("******SVN版本号不能为空******");
                            return;
                        }
                        int SVNNumber;
                        try {
                            SVNNumber = Integer.valueOf(SVNStr);
                        } catch (Exception e2) {
                            e2.printStackTrace();
                            logArea.setText("******SVN版本号只能为数字******");
                            return;
                        }
                        efbsn = new ExportFileBySVNNumberThread(rootPath, 
                                exportPath, SVNNumber, logArea, pbar);
                        efbsn.start();
                    }
                });
                dialog.setLayout(new GridLayout(3, 1));
                dialog.add(rootPanel);
                dialog.add(exportPanel);
                dialog.add(SVNNumberPanel);
                dialog.setVisible(true);
            }

        });
    }

    /**
     * 为执行导出脚本按钮添加监听
     */
    public void addListenerToExportFileButton() {
        exportFileButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (executeSqlThread == null || !executeSqlThread.isAlive()
                        && executeExportFileThread == null || !executeExportFileThread.isAlive()
                        && createSqlWithExcelThread == null || !createSqlWithExcelThread.isAlive()) {
                    if (importPath.getText().trim().equals("")) {
                        logArea.setText("********没有资源列表********");
                    } else if (importPath.getText().trim().endsWith(HitConstants.FILE_TYPE_XLS)
                            && doCheck()) {
                        createSqlWithExcelThread = new CreateSqlWithExcelThread(new File(importPath
                                .getText().trim()), logArea, pbar, exportPath.getText().trim());
                        createSqlWithExcelThread.start();
                    } else if (importPath.getText().trim().endsWith(HitConstants.FILE_TYPE_SQL)
                            || importPath.getText().trim().endsWith(HitConstants.FILE_TYPE_TXT)) {
                        executeExportFileThread = new ExecuteExportFileThread(readerFiles(), logArea,
                                pbar, exportPath.getText().trim());
                        executeExportFileThread.start();
                    }
                }
            }
        });
    }

    /**
     * 为执行脚本按钮添加监听
     */
    public void addListenerToExecuteButton() {
        executeButt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (doCheck()) {
                    if (executeSqlThread == null || !executeSqlThread.isAlive()
                            && executeExportFileThread == null || !executeExportFileThread.isAlive()
                            && createSqlWithExcelThread == null
                            || !createSqlWithExcelThread.isAlive()) {
                        executeSqlThread = new ExecuteSqlThread(exportPath.getText().trim(), logArea,
                                pbar);
                        executeSqlThread.start();
                    }
                }
            }
        });
    }

    /**
     * 执行前校验
     * 
     * @return
     */
    @SuppressWarnings("deprecation")
    private boolean doCheck() {
        if (url.getText().trim().equals("")) {
            logArea.setText("********数据库连接不能为空********");
            return false;
        } else if (userName.getText().trim().equals("")) {
            logArea.setText("********数据库用户名不能为空********");
            return false;
        } else if (pwd.getText().trim().equals("")) {
            logArea.setText("********数据库密码不能为空********");
            return false;
        } else if (!dbAccess.setConnection(url.getText().trim(), userName.getText().trim(), pwd
                .getText().trim())) {
            logArea.setText("********不能连接数据库********");
            return false;
        } else if (exportPath.getText().trim().equals("")) {
            exportPath.setText(currentDir);
            logArea.setText("********连接数据库成功********\n********没有选择另存路径，程序设置为默认路径********");
        }
        return true;
    }

    /**
     * 弹出选择文件窗口
     */
    public void fileChoose() {
        chooser = new JFileChooser(HitConstants.FILE_CHOOSER_DEFAULT_DRICTORY);
        String sqlSuffix = HitConstants.FILE_TYPE_SQL.replace(".", "");
        String txtSuffix = HitConstants.FILE_TYPE_TXT.replace(".", "");
        String xlsSuffix = HitConstants.FILE_TYPE_XLS.replace(".", "");
        FileNameExtensionFilter filter = new FileNameExtensionFilter(sqlSuffix + " & " + txtSuffix
                + " & " + xlsSuffix, sqlSuffix, txtSuffix, xlsSuffix);
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(this);
        File file;
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = chooser.getSelectedFile();
        } else if (importPath.getText().trim().length() > 1) {
            file = new File(importPath.getText().trim());
        } else {
            return;
        }
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), HitConstants.FILE_ENCODING));
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        importPath.setText(file.getAbsolutePath());
    }

    /**
     * 弹出选择文件夹窗口
     */
    public void dirChoose(JTextField pathField) {
        chooser = new JFileChooser(HitConstants.FILE_CHOOSER_DEFAULT_DRICTORY);
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = chooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            try {
                pathField.setText(chooser.getSelectedFile().getCanonicalPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            if (pathField.getText().trim().equals("")) {
                pathField.setText(currentDir);
            }
        }
    }

    /**
     * 根据导出文件列表提供的路径，找到脚本文件的路径
     * 
     * @return files：读进程序的文件清单
     */
    private List<File> readerFiles() {
        List<File> files = new ArrayList<File>();
        String filePathList = importPath.getText().trim();
        try {
            File file = new File(filePathList);
            String root = file.getCanonicalPath();
            root = root.substring(0, root.indexOf("db"));
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), HitConstants.FILE_ENCODING));
            String tmpPath = "";
            while ((tmpPath = reader.readLine()) != null) {
                if (!tmpPath.startsWith("--") && !tmpPath.startsWith("/*")
                        && !tmpPath.startsWith("*") && !tmpPath.startsWith("*/")
                        && !tmpPath.startsWith("//")
                        && tmpPath.contains(HitConstants.FILE_TYPE_SQL)) {
                    files.add(new File(root + "\\" + tmpPath.replace("/", "\\")));
                }
            }
            reader.close();
        } catch (Exception e) {
            logArea.setText("************************非法脚本文件************************");
            e.printStackTrace();
        }
        return files;
    }

    /**
     * 程序入口方法
     * 
     * @param args
     */
    public static void main(String[] args) {
        ExecuteSqlWin win = new ExecuteSqlWin();
        win.addListeners();
        win.setVisible(true);
    }

    public BufferedReader getReader() {
        return reader;
    }

    public void setReader(BufferedReader reader) {
        this.reader = reader;
    }

    public JTextField getUrl() {
        return url;
    }

    public void setUrl(JTextField url) {
        this.url = url;
    }

    public JTextField getUserName() {
        return userName;
    }

    public void setUserName(JTextField userName) {
        this.userName = userName;
    }

    public JPasswordField getPwd() {
        return pwd;
    }

    public void setPwd(JPasswordField pwd) {
        this.pwd = pwd;
    }

    public JTextField getImportPath() {
        return importPath;
    }

    public void setImportPath(JTextField importPath) {
        this.importPath = importPath;
    }

    public JButton getImportButt() {
        return importButt;
    }

    public void setImportButt(JButton importButt) {
        this.importButt = importButt;
    }

    public JTextField getExportPath() {
        return exportPath;
    }

    public void setExportPath(JTextField exportPath) {
        this.exportPath = exportPath;
    }

    public JButton getExportButt() {
        return exportButt;
    }

    public void setExportButt(JButton exportButt) {
        this.exportButt = exportButt;
    }

    public JButton getGenerateTestDataButt() {
        return generateTestDataButt;
    }

    public void setGenerateTestDataButt(JButton generateTestDataButt) {
        this.generateTestDataButt = generateTestDataButt;
    }

    public JButton getExportFileBySVNNumberButt() {
        return exportFileBySVNNumberButt;
    }

    public void setExportFileBySVNNumberButt(JButton exportFileBySVNNumberButt) {
        this.exportFileBySVNNumberButt = exportFileBySVNNumberButt;
    }

    public JButton getExportFileButt() {
        return exportFileButt;
    }

    public void setExportFileButt(JButton exportFileButt) {
        this.exportFileButt = exportFileButt;
    }

    public JButton getExecuteButt() {
        return executeButt;
    }

    public void setExecuteButt(JButton executeButt) {
        this.executeButt = executeButt;
    }

    public JTextArea getLogArea() {
        return logArea;
    }

    public void setLogArea(JTextArea logArea) {
        this.logArea = logArea;
    }

    public JProgressBar getPbar() {
        return pbar;
    }

    public void setPbar(JProgressBar pbar) {
        this.pbar = pbar;
    }

    public String getCurrentDir() {
        return currentDir;
    }

    public void setCurrentDir(String currentDir) {
        this.currentDir = currentDir;
    }

}
